# coding: utf-8
# author: t_wolf
#
# for frame control
#

from framework.core.kernel import *

curr_path = get_abs_path(CURR_FILE_POSITION)


def helper(*args):
    print """

help for %s

    app: {
            add [app]: 创建应用
            del [app]: 删除应用
         enable [app]: 设置app有效
        disable [app]: 设置app无效
                 list: 应用列表
    },
    frame: {
        mode: {
                 show: 查看当前模式
               toggle: 切换当前模式
        },
        runtime: {
                 show: 查看当前运行模式
               toggle: 切换当前运行模式
        },
          start: 启动框架
           stop: 停止框架
        restart: 重启框架
        upgrade: 维护框架 [START|STOP|RESUME]
    },
    env: {
        deploy: 部署框架依赖
         clean: 清理框架目录,还原到原始目录结构
    },
    help: 显示此帮助

""" % sys.argv[0]
    sys.exit(
        FRAME_DEFINE.EXIT_CODE_DEFILE.EXIT_BY_WRONG_ARGUMENTS
    )


@check_args(args_num=1, on_error=helper)
def create_app(app_name):
    target_app = os.path.join(
        os.path.join(curr_path, CONFIGS.FRAME.APP_PATH),
        app_name
    )

    if re.search('[-`@#$!%^&*()]', app_name):
        write_console("[ERROR] 应用名称中不能包含[-`@#$!%^&*()]的特殊字符。")
        sys.exit(
            FRAME_DEFINE.EXIT_CODE_DEFILE.EXIT_BY_WRONG_ARGUMENTS
        )

    if not os.path.exists(target_app):

        platform_copy_directory(
            os.path.join(curr_path, "framework/app_template"),
            target_app
        )
        replace_file_words(
            os.path.join(target_app, "settings/configs.py"),
            {
                '#APP_NAME#': app_name,
                '#APP_PATH#': '%s/%s' % (CONFIGS.FRAME.APP_PATH, app_name),
                '#LOG_NAME#': '%s.log' % app_name,
                '#COOKIE_NAME#': '%s_cookie' % app_name,
            }
        )

    else:
        write_console("Application named [%s] already exists." % app_name)


@check_args(args_num=1, on_error=helper)
def remove_app(app_name):
    target_app = os.path.join(
        os.path.join(curr_path, CONFIGS.FRAME.APP_PATH),
        app_name
    )

    if os.path.exists(target_app):

        platform_remove_directory(target_app)

    else:
        write_console("Application named [%s] not exists." % app_name)


@check_args(on_error=helper)
def enable_app(*app_names):
    apps_info = scan_app_list(CONFIGS.FRAME.APP_PATH)
    app_paths = (
        [(app_info[0], app_info[1]) for app_info in apps_info] if app_names[0] == 'all' else
        [(app_info[0], app_info[1]) for app_name in app_names for app_info in apps_info if app_info[0] == app_name]
    ) if len(app_names) else helper()

    for app in app_paths:

        target_app = os.path.join(ROOT_PATH, app[1])

        if os.path.exists(target_app):

            replace_file_words(
                os.path.join(target_app, "settings/configs.py"),
                {
                    "'enabled': \w+?,": "'enabled': True,"
                }
            )

        else:
            write_console("Application named [%s] not exists." % app[0])


@check_args(on_error=helper)
def disable_app(*app_names):
    apps_info = scan_app_list(CONFIGS.FRAME.APP_PATH)
    app_paths = (
        [(app_info[0], app_info[1]) for app_info in apps_info] if app_names[0] == 'all' else
        [(app_info[0], app_info[1]) for app_name in app_names for app_info in apps_info if app_info[0] == app_name]
    ) if len(app_names) else helper()

    for app in app_paths:

        target_app = os.path.join(ROOT_PATH, app[1])

        if os.path.exists(target_app):

            replace_file_words(
                os.path.join(target_app, "settings/configs.py"),
                {
                    "'enabled': \w+?,": "'enabled': False,"
                }
            )

        else:
            write_console("Application named [%s] not exists." % app[0])


@check_args(on_error=helper)
def apps_list():
    if CONFIGS.FRAME.MULTI_APP:
        write_console("App List:")
        fw = FormatWriter(in_separator=',', fell=8, header='\t')
        fw.set_title("Name,Path,Enabled")
        for name, path, state in scan_app_list(CONFIGS.FRAME.APP_PATH):
            fw.eat("%s,%s,%s" % (name, path, state))

        fw.spit()
    else:
        current_mode()


@check_args(on_error=helper)
def current_mode():
    write_console("Now Mode: %s" % ("[MULTI]" if CONFIGS.FRAME.MULTI_APP else "[SINGLE]"))


@check_args(on_error=helper)
def current_run_mode():
    write_console("Now Runtime Mode: [%s]" % CONFIGS.FRAME.RUN_OPTIONS.MODE)


@check_args(on_error=helper)
def change_mode():
    target_conf = os.path.join(get_abs_path(CURR_FILE_POSITION), "framework/configure/configs.py")
    if CONFIGS.FRAME.MULTI_APP:
        replace_file_words(target_conf, {"'MULTI_APP': \w+?,": "'MULTI_APP': False,"})
    else:
        replace_file_words(target_conf, {"'MULTI_APP': \w+?,": "'MULTI_APP': True,"})


@check_args(on_error=helper)
def change_run_mode():
    target_conf = os.path.join(get_abs_path(CURR_FILE_POSITION), "framework/configure/configs.py")
    if CONFIGS.FRAME.RUN_OPTIONS.MODE == 'UWSGI':
        replace_file_words(target_conf, {"'MODE': '\w+?',": "'MODE': 'DEFAULT',"})
    else:
        replace_file_words(target_conf, {"'MODE': '\w+?',": "'MODE': 'UWSGI',"})


@check_args(on_error=helper)
def start():
    run_mode = CONFIGS.FRAME.RUN_OPTIONS.MODE
    if run_mode == 'DEFAULT' or run_mode == '':
        system_command("python www.py %d > %s &" % (
            CONFIGS.FRAME.RUN_OPTIONS.DEFAULT.LISTEN_PORT, CONFIGS.FRAME.RUN_OPTIONS.ENV_LOG))
    elif run_mode == 'UWSGI':
        uwsgi_configs = CONFIGS.FRAME.RUN_OPTIONS.UWSGI
        uwsgi_file = '''# settings for uwsgi server , generate time: [%s]
[uwsgi]
http = :%d
stats = :%d
workers = %d
threads = %d
chdir = %s
wsgi-file = %s
vacuum = %s
disable-logging = %s
pidfile = /tmp/uwsgi.pid
daemonize = %s
master = True
# lazy = True
# static-maps
''' % (
            get_current_time(),
            uwsgi_configs.http, uwsgi_configs.stats, uwsgi_configs.workers, uwsgi_configs.threads,
            ROOT_PATH, "%s/www.py" % ROOT_PATH,
            uwsgi_configs.vacuum, uwsgi_configs.disable_logging,
            "%s/uwsgi-server.log" % ROOT_PATH
        )
        with open('framework/configure/uwsgi.ini', 'wb') as wsgi:
            wsgi.write(uwsgi_file)
            if CONFIGS.FRAME.MULTI_APP:
                for name, path, enabled in scan_app_list(CONFIGS.FRAME.APP_PATH):
                    if enabled:
                        wsgi.write(
                            "static-map = /%s/resources=%s%s" % (
                                name,
                                os.path.join(ROOT_PATH, path, "resources"),
                                os.linesep
                            )
                        )
            wsgi.write("static-map = /static=%s/static" % ROOT_PATH)

        _cmd_uwsgi = uwsgi_configs.uwsgi_path if len(uwsgi_configs.uwsgi_path) else "uwsgi"
        system_command("%s %s" % (_cmd_uwsgi, os.path.join(ROOT_PATH, 'framework/configure/uwsgi.ini')))

    else:
        logger.error("Unknown mode [%s] for startup frame." % run_mode)


@check_args(on_error=helper)
def stop():
    run_mode = CONFIGS.FRAME.RUN_OPTIONS.MODE
    if run_mode == 'DEFAULT':
        if PLATFORM in ('darwin', 'linux2'):
            cmd_str = "kill -9 $(ps -ef | grep python | grep %s | awk '{print $2}') > /dev/null 2>&1" % (
                CONFIGS.FRAME.RUN_OPTIONS.DEFAULT.LISTEN_PORT)
        elif PLATFORM in ('win32',):
            cmd_str = "for /f \"tokens=2\" %i in ('tasklist ^| find \"python.exe\"') do @taskkill /PID %i /T > nul"
        else:
            write_console("This Platform not Supported.")
            sys.exit(
                FRAME_DEFINE.EXIT_CODE_DEFILE.EXIT_BY_WRONG_ARGUMENTS
            )
    elif run_mode == 'UWSGI':
        if PLATFORM in ('darwin', 'linux2'):
            cmd_str = "kill -9 $(ps -ef | grep uwsgi | grep %s | grep -v grep | awk '{print $2}') > /dev/null 2>&1" % (
                os.path.join(ROOT_PATH, 'framework/configure/uwsgi.ini'))
        elif PLATFORM in ('win32',):
            cmd_str = "for /f \"tokens=2\" %i in ('tasklist ^| find \"uwsgi.exe\"') do @taskkill /PID %i /T > nul"
    else:
        return None

    return system_command(cmd_str)


@check_args(on_error=helper)
def start_fixed_server():
    if CONFIGS.FRAME.RUN_OPTIONS.MODE.upper() == 'DEFAULT':
        port = CONFIGS.FRAME.RUN_OPTIONS.DEFAULT.LISTEN_PORT
    elif CONFIGS.FRAME.RUN_OPTIONS.MODE.upper() == 'UWSGI':
        port = CONFIGS.FRAME.RUN_OPTIONS.UWSGI.http
    else:
        raise RuntimeError("UnKnown RunMode.")
    system_command("python framework/maintenance.py %d > fixed.log &" % port)


@check_args(on_error=helper)
def stop_fixed_server():
    if CONFIGS.FRAME.RUN_OPTIONS.MODE.upper() == 'DEFAULT':
        port = CONFIGS.FRAME.RUN_OPTIONS.DEFAULT.LISTEN_PORT
    elif CONFIGS.FRAME.RUN_OPTIONS.MODE.upper() == 'UWSGI':
        port = CONFIGS.FRAME.RUN_OPTIONS.UWSGI.http
    else:
        raise RuntimeError("UnKnown RunMode.")

    if PLATFORM in ('darwin', 'linux2'):
        cmd_str = "kill -9 $(ps -ef | grep python | grep %s | awk '{print $2}') > /dev/null 2>&1" % port
    elif PLATFORM in ('win32',):
        cmd_str = "for /f \"tokens=2\" %i in ('tasklist ^| find \"python.exe\"') do @taskkill /PID %i /T > nul"
    else:
        write_console("This Platform not Supported.")
        sys.exit(
            FRAME_DEFINE.EXIT_CODE_DEFILE.EXIT_BY_WRONG_ARGUMENTS
        )
    return system_command(cmd_str)


@check_args(on_error=helper)
def restart():
    stop()
    start()


@check_args(args_num=1, on_error=helper)
def upgrade(state):
    if state.upper() == 'START':
        stop()
        start_fixed_server()
    elif state.upper() == 'STOP':
        stop_fixed_server()
    elif state.upper() == 'RESUME':
        stop_fixed_server()
        start()
    else:
        helper()


@check_args(on_error=helper)
def deploy():
    pass


@check_args(on_error=helper)
def clean():
    apps_path = os.path.join(curr_path, CONFIGS.FRAME.APP_PATH)
    for name, path, state in scan_app_list(apps_path):
        system_remove(os.path.join(apps_path, path))


commands = {
    'app': {
        'add': create_app,
        'del': remove_app,
        'list': apps_list,
        'enable': enable_app,
        'disable': disable_app,
    },
    'frame': {
        'mode': {
            'show': current_mode,
            'toggle': change_mode,
        },
        'runtime': {
            'show': current_run_mode,
            'toggle': change_run_mode,
        },
        'start': start,
        'stop': stop,
        'restart': restart,
        'upgrade': upgrade,
    },
    'env': {
        'deploy': deploy,
        'clean': clean,
    },
    'help': helper
}


def main():
    dynamic_callee(
        commands, sys.argv[1:], helper
    )


if __name__ == '__main__':
    main()
